/* Copyright (c) 2006 by M Aamir Maniar 
 * 
 * Permission is hereby granted, free of charge, to any person obtaining 
 * a copy of this software and associated documentation files (the 
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to 
 * permit persons to whom the Software is furnished to do so, subject to 
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * 
 * */

namespace Generic.DataStructures
{
    using System;
    using SysGeneric = System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// Represents a queue that trigger events on certain operations.
    /// </summary>
    /// <typeparam name="T"></typeparam>
	public class QueueWithEvents<T> : IQueue<T>
    {
        #region public QueueWithEvents(IQueue<T> queue)
        public QueueWithEvents(IQueue<T> queue)
        {
            _internalQueue = queue;
        }
        #endregion

        #region public IQueue<T> InternalQueue
        private IQueue<T> _internalQueue;
        public IQueue<T> InternalQueue
        {
            get { return _internalQueue; }
            set { _internalQueue = value; }
        }
        #endregion

        #region public void Enqueue(T item)
        /// <summary>
        /// Add the item at the end of the <see cref="IQueue&lt;T&gt;"/>.
        /// </summary>
        /// <param name="item">The item to be Enqueueed.</param>
		public void Enqueue(T item)
		{
            OnBeforeEnqueue(new QueueEventArgs<T>(item));
            _internalQueue.Enqueue(item);
            OnAfterEnqueue(new QueueEventArgs<T>(item));

        }
        #endregion

        #region Event: BeforeEnqueue
        /// <summary>
        /// Occurs when before Enqueue.
        /// </summary>
        public event EventHandler<QueueEventArgs<T>> BeforeEnqueue = null;
        /// <summary>
        /// Raises the <see cref="E:BeforeEnqueue"/> event.
        /// </summary>
        /// <param name="e">The <see cref="Generic.DataStructures.QueueEventArgs&lt;T&gt;"/> instance containing the event data.</param>
        protected virtual void OnBeforeEnqueue(QueueEventArgs<T> e)
        {
            if (BeforeEnqueue != null)
                BeforeEnqueue(this, e);
        }
        #endregion

        #region Event: AfterEnqueue
        /// <summary>
        /// Occurs when After Enqueue.
        /// </summary>
        public event EventHandler<QueueEventArgs<T>> AfterEnqueue = null;
        /// <summary>
        /// Raises the <see cref="E:AfterEnqueue"/> event.
        /// </summary>
        /// <param name="e">The <see cref="Generic.DataStructures.QueueEventArgs&lt;T&gt;"/> instance containing the event data.</param>
        protected virtual void OnAfterEnqueue(QueueEventArgs<T> e)
        {
            if (AfterEnqueue != null)
                AfterEnqueue(this, e);
        }
        #endregion

        #region public T Dequeue ()
        /// <summary>
        /// Dequeues the top most item from the <see cref="IQueue&lt;T&gt;"/>.
        /// </summary>
        /// <returns>The item Dequeueed.</returns>
        public T Dequeue ()
		{
            OnBeforeDequeue(new EventArgs());
            T item = _internalQueue.Dequeue();
            OnAfterDequeue(new EventArgs());
            return item;
        }
        #endregion

        #region Event: BeforeDequeue
        /// <summary>
        /// Occurs when before Dequeue.
        /// </summary>
        public event EventHandler BeforeDequeue = null;
        /// <summary>
        /// Raises the <see cref="E:BeforeDequeue"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnBeforeDequeue(EventArgs e)
        {
            if (BeforeDequeue != null)
                BeforeDequeue(this, e);
        }
        #endregion

        #region Event: AfterDequeue
        /// <summary>
        /// Occurs when [after dequeue].
        /// </summary>
        public event EventHandler AfterDequeue = null;
        protected virtual void OnAfterDequeue(EventArgs e)
        {
            if (AfterDequeue != null)
                AfterDequeue(this, e);
        }
        #endregion

        #region public bool FixedSize
        /// <summary>
        /// Gets or sets a value indicating whether <see cref="IQueue&lt;T&gt;"/> is fixed sized.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if <see cref="IQueue&lt;T&gt;"/> is fixed sized; otherwise, <c>false</c>.
        /// </value>
        /// <remarks>
        /// By default <see cref="IQueue&lt;T&gt;"/> is fixed sized.
        /// </remarks>
		public bool FixedSize
		{
			get
			{
                return _internalQueue.FixedSize;
			}
			set
			{
                _internalQueue.FixedSize = value;
			}
        }
        #endregion

        #region public bool IsFull
        /// <summary>
        /// Gets a value indicating whether <see cref="IQueue&lt;T&gt;"/> is full.
        /// </summary>
        /// <value><c>true</c> if this instance is full; otherwise, <c>false</c>.</value>
		public bool IsFull
		{
			get 
            {
                return _internalQueue.IsFull;
            }
        }
        #endregion

        #region public bool IsEmpty
        /// <summary>
        /// Gets a value indicating whether this instance is empty.
        /// </summary>
        /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
        public bool IsEmpty
		{
			get 
            {
                return _internalQueue.IsEmpty;
            }
        }
        #endregion

        #region public bool IsSynchronized
        /// <summary>
        /// Gets a value indicating whether this instance is synchronized.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is synchronized; otherwise, <c>false</c>.
        /// </value>
        public bool IsSynchronized
		{
			get 
            {
                return _internalQueue.IsSynchronized;
            }
        }
        #endregion

        #region public object SyncRoot
        /// <summary>
        /// Gets the SyncRoot, an object that help to created synchronized objects.
        /// </summary>
        /// <value>The sync root.</value>
        public object SyncRoot
		{
			get 
            {
                return _internalQueue.SyncRoot;
            }
        }
        #endregion

        #region ICollection<T> Members

        public void Add(T item)
		{
            Enqueue(item);
		}


		public void Clear()
		{
            OnBeforeClear(new EventArgs());
            _internalQueue.Clear();
		}

        public event EventHandler BeforeClear = null;
        protected virtual void OnBeforeClear(EventArgs e)
        {
            if (BeforeClear != null)
                BeforeClear(this, e);
        }

        public event EventHandler AfterClear = null;
        protected virtual void OnAfterClear(EventArgs e)
        {
            if (AfterClear != null)
                AfterClear(this, e);
        }

		public bool Contains(T item)
		{
            return _internalQueue.Contains(item);
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
            _internalQueue.CopyTo(array, arrayIndex);
		}

		public int Count
		{
			get 
            {
                return _internalQueue.Count;
            }
		}

		public bool IsReadOnly
		{
            get { return _internalQueue.IsReadOnly; }
		}

		public bool Remove(T item)
		{
            return _internalQueue.Remove(item);
		}

		#endregion

		#region IEnumerable<T> Members

		public SysGeneric.IEnumerator<T> GetEnumerator()
		{
            return _internalQueue.GetEnumerator();
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
            return _internalQueue.GetEnumerator() as System.Collections.IEnumerator;
		}

		#endregion

		#region ICloneable Members

		public object Clone()
		{
            return _internalQueue.Clone();
		}

		#endregion

        #region IQueue<T> Members


        public T First
        {
            get { return _internalQueue.First; }
        }

        public T Last
        {
            get { return _internalQueue.Last; }
        }

        #endregion
    }
}
